package com.light.mytext.websocket;

import android.util.Base64;
import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.light.mytext.kedavoicetotext.EncryptUtil;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;
import java.util.Objects;
import java.util.TimeZone;
import java.util.concurrent.CountDownLatch;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import okhttp3.HttpUrl;


public class WebSockNet {
    private static final String appid = "5fa8e182"; //在控制台-我的应用获取
    private static final String apiSecret = "34d7fe6b5f1e6d7791dbabfc594f1585"; //在控制台-我的应用-语音听写（流式版）获取
    private static final String apiKey = "18d5c07002252fb750c83ca57ae8d23f"; //在控制台-我的应用-语音听写（流式版）获取
    // 请求地址
    private static final String hostUrl = "https://iat-api.xfyun.cn/v2/iat"; //中英文，http url 不支持解析 ws/ schema
    private static final String file = "/storage/emulated/0/Android/data/com.tencent.mobileqq/Tencent/QQfile_recv/16k_10.pcm";
    public static final int StatusFirstFrame = 0;
    public static final int StatusContinueFrame = 1;
    public static final int StatusLastFrame = 2;
    private static MyWebSockNet client;

    public static void main() throws Exception {
        CountDownLatch handshakeSuccess = new CountDownLatch(1);
        CountDownLatch connectClose = new CountDownLatch(1);
        String authUrl = getAuthUrl(hostUrl, apiKey, apiSecret);
        String urlaa = authUrl.replace("http://", "ws://").replace("https://", "wss://");
        URI url = new URI(urlaa);
        client = new MyWebSockNet(url, handshakeSuccess, connectClose);
        client.connect();
        // 等待握手成功
        handshakeSuccess.await();
        Log.i("RTASRTest", " 开始发送音频数据");
    }

    static class MyWebSockNet extends WebSocketClient {
        private CountDownLatch handshakeSuccess;
        private CountDownLatch connectClose;

        public MyWebSockNet(URI serverUri, CountDownLatch handshakeSuccess, CountDownLatch connectClose) {
            super(serverUri);
            this.handshakeSuccess = handshakeSuccess;
            this.connectClose = connectClose;
        }


        @Override
        public void onOpen(ServerHandshake serverHandshake) {
            Log.i("WebSockNet", "\t连接建立成功！");
            new Thread() {
                /*try (FileInputStream fs = new FileInputStream(file)) {

                    //连接成功，开始发送数据
                    int frameSize = 1280; //每一帧音频的大小,建议每 40ms 发送 122B
                    int intervel = 40;
                    int status = 0;  // 音频的状态
                    byte[] buffer = new byte[frameSize];
                    // 发送音频
                    end:
                    while (true) {
                        int len = 0;
                        try {
                            len = fs.read(buffer);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        if (len == -1) {
                            status = StatusLastFrame;  //文件读完，改变status 为 2
                        }
                        switch (status) {
                            case StatusFirstFrame:   // 第一帧音频status = 0
                                JsonObject frame = new JsonObject();
                                JsonObject business = new JsonObject();  //第一帧必须发送
                                JsonObject common = new JsonObject();  //第一帧必须发送
                                JsonObject data = new JsonObject();  //每一帧都要发送
                                // 填充common
                                common.addProperty("app_id", appid);
                                //填充business
                                business.addProperty("language", "zh_cn");
                                //business.addProperty("language", "en_us");//英文
                                //business.addProperty("language", "ja_jp");//日语，在控制台可添加试用或购买
                                //business.addProperty("language", "ko_kr");//韩语，在控制台可添加试用或购买
                                //business.addProperty("language", "ru-ru");//俄语，在控制台可添加试用或购买
                                business.addProperty("domain", "iat");
                                business.addProperty("accent", "mandarin");//中文方言请在控制台添加试用，添加后即展示相应参数值
                                //business.addProperty("nunum", 0);
                                //business.addProperty("ptt", 0);//标点符号
                                //business.addProperty("rlang", "zh-hk"); // zh-cn :简体中文（默认值）zh-hk :繁体香港(若未授权不生效，在控制台可免费开通)
                                //business.addProperty("vinfo", 1);
                                business.addProperty("dwa", "wpgs");//动态修正(若未授权不生效，在控制台可免费开通)
                                //business.addProperty("nbest", 5);// 句子多候选(若未授权不生效，在控制台可免费开通)
                                //business.addProperty("wbest", 3);// 词级多候选(若未授权不生效，在控制台可免费开通)
                                //填充data
                                data.addProperty("status", StatusFirstFrame);
                                data.addProperty("format", "audio/L16;rate=16000");
                                data.addProperty("encoding", "raw");
                                data.addProperty("audio", Base64.encodeToString((Arrays.copyOf(buffer, len)), Base64.NO_WRAP));
//                        data.addProperty("audio", new String(Arrays.copyOf(buffer, len)));
//                            data.addProperty("audio", Base64.getEncoder().encodeToString(Arrays.copyOf(buffer, len)));
                                //填充frame
                                frame.add("common", common);
                                frame.add("business", business);
                                frame.add("data", data);
                                client.send(frame.toString());
                                status = StatusContinueFrame;  // 发送完第一帧改变status 为 1
                                break;
                            case StatusContinueFrame:  //中间帧status = 1
                                JsonObject frame1 = new JsonObject();
                                JsonObject data1 = new JsonObject();
                                data1.addProperty("status", StatusContinueFrame);
                                data1.addProperty("format", "audio/L16;rate=16000");
                                data1.addProperty("encoding", "raw");
                                data1.addProperty("audio", Base64.encodeToString((Arrays.copyOf(buffer, len)), Base64.NO_WRAP));
//                            data1.addProperty("audio", Base64.getEncoder().encodeToString(Arrays.copyOf(buffer, len)));
                                frame1.add("data", data1);
                                client.send(frame1.toString());
                                // System.out.println("send continue");
                                break;
                            case StatusLastFrame:    // 最后一帧音频status = 2 ，标志音频发送结束
                                JsonObject frame2 = new JsonObject();
                                JsonObject data2 = new JsonObject();
                                data2.addProperty("status", StatusLastFrame);
                                data2.addProperty("audio", "");
                                data2.addProperty("format", "audio/L16;rate=16000");
                                data2.addProperty("encoding", "raw");
                                frame2.add("data", data2);
                                client.send(frame2.toString());
                                System.out.println("sendlast");
                                break end;
                        }
                        Thread.sleep(intervel); //模拟音频采样延时
                    }
                    System.out.println("all data is send");


                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }*/
            }.start();
        }

        @Override
        public void onMessage(String msg) {
            JSONObject msgObj = JSON.parseObject(msg);
            String action = msgObj.getString("action");
            if (Objects.equals("started", action)) {
                // 握手成功
                Log.i("WebSockNet", "握手成功");
                handshakeSuccess.countDown();
            }
        }

        @Override
        public void onClose(int i, String s, boolean b) {
            Log.i("WebSockNet", "onClose");
        }

        @Override
        public void onError(Exception e) {
            Log.i("WebSockNet", "onError" + e.getMessage());
        }
    }

    public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {
        URL url = new URL(hostUrl);
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = format.format(new Date());
        StringBuilder builder = new StringBuilder("host: ").append(url.getHost()).append("\n").//
                append("date: ").append(date).append("\n").//
                append("GET ").append(url.getPath()).append(" HTTP/1.1");
        //System.out.println(builder);
        Charset charset = Charset.forName("UTF-8");
        Mac mac = Mac.getInstance("hmacsha256");
        SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(charset), "hmacsha256");
        mac.init(spec);
        byte[] hexDigits = mac.doFinal(builder.toString().getBytes(charset));
//        String sha = Base64.getEncoder().encodeToString(hexDigits);
        String sha = Base64.encodeToString(hexDigits, Base64.NO_WRAP);

        //System.out.println(sha);
        String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
        //System.out.println(authorization);
        HttpUrl httpUrl = HttpUrl.parse("https://" + url.getHost() + url.getPath()).newBuilder().//
                addQueryParameter("authorization", Base64.encodeToString(authorization.getBytes(charset), Base64.NO_WRAP)).
//                addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(charset))).//
        addQueryParameter("date", date).//
                addQueryParameter("host", url.getHost()).//
                build();
        return httpUrl.toString();
    }


}
